﻿using System;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Dqaqs.Data;
using Dqaqs.Services;
using Dqaqs.Services.ServiceContracts;
using Dqaqs.Web.Common;

namespace Dqaqs.Web.Controllers
{
	public class DataSourceController : EditableController
	{
		public ActionResult Index()
		{
			try
			{
				MenuService.Set("Data Sources", "List Data Sources");
				var svc = GetDataSourceService();
				var svcs = svc.ListDataSources(ProjectContext.Project.Id);
				return View(svcs);
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		public ActionResult Details(int id)
		{
			try
			{
				MenuService.Set("Data Sources", "List of Data Sources");
				var svc = GetDataSourceService();
				var ds = svc.GetDataSource(id);
				return View(ds);
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		public ActionResult New()
		{
			try
			{
				MenuService.Set("Data Sources", "New Data Source");
				var projectId = ProjectContext.Project.Id;
				ArgumentCheck.IsNotNull(projectId, "projectId");
				var rv = new DataSource {ProjectId = projectId};
				return View(rv);
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		[HttpPost]
		public ActionResult New(DataSource dSource)
		{
			try
			{
				MenuService.Set("Data Sources", "New Data Source");
				var svc = GetDataSourceService();
				dSource.ProjectId = ProjectContext.Project.Id;
				dSource.Schema = String.Empty;
				svc.NewDataSource(dSource);
				return RedirectToAction("Index");
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		public ActionResult Edit(int id)
		{
			try
			{
				MenuService.Set("Data Sources", "List of Data Sources");
				var svc = GetDataSourceService();
				var ds = svc.GetDataSource(id);
				var jss = new JavaScriptSerializer();
				ds.Schema = jss.Serialize(ds.SchemaDefinition);
				return View(ds);
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		[HttpPost]
		public ActionResult Edit(DataSource dataSource)
		{
			try
			{
				MenuService.Set("Data Sources", "List of Data Sources");
				var svc = GetDataSourceService();
				dataSource.Schema = JsonHelper.GenerateSchemaFromJson(dataSource.Schema);
				svc.UpdateDataSource(dataSource);

				return RedirectToAction("Index");
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		public ActionResult Delete(int id)
		{
			try
			{
				var svc = GetDataSourceService();
				svc.DeleteDataSource(id);

				return RedirectToAction("Index");
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		public ActionResult GetSchema(int id)
		{
			var svc = GetDataSourceService();
			var ds = svc.GetDataSource(id);
			var schema = ds.Schema;
			if (string.IsNullOrWhiteSpace(schema))
			{
				return Json(new { tables = "" }, JsonRequestBehavior.AllowGet);
			}
			return Json(ds.SchemaDefinition, JsonRequestBehavior.AllowGet);
		}

		public ActionResult UploadData(int id)
		{
			try
			{
				MenuService.Set("Data Sources", null);
				var svc = GetDataSourceService();
				var ds = svc.GetDataSource(id);
				ViewBag.Id = ds.Id;
				ViewBag.ProjectId = ds.ProjectId;
				ViewBag.Title = ds.Title;
				return View(ds.SchemaDefinition);
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		[HttpPost]
		public ActionResult UploadData(Guid projectId, int id)
		{
			try
			{
				MenuService.Set("Data Source", null);
				var svc = GetDataSourceService();
				var prj = svc.GetDataSource(id);
				ViewBag.Id = prj.Id;
				ViewBag.ProjectId = prj.ProjectId;
				ViewBag.Title = prj.Title;
				// ReSharper disable PossibleNullReferenceException
				foreach (var fk in Request.Files.AllKeys)
				{
						if (string.IsNullOrEmpty(Request.Files[fk].FileName) || Request.Files[fk].ContentLength == 0)
							continue;
						svc.UploadData(new UploadMessage
						               	{
						               		DataSourceId = id,
						               		Table = fk.Remove(0, "upload=".Length),
						               		FileStream =
						               			ReadStream(Request.Files[fk].InputStream).Split("\r\n".ToCharArray(),
						               			                                                StringSplitOptions.RemoveEmptyEntries)
						               	});
				}
				var uploaded = Request.Files.AllKeys.Select(key => Tuple.Create(key, Request.Files[key].FileName));
				ViewBag.Uploaded = uploaded.Where(t => !string.IsNullOrEmpty(t.Item2)).ToArray();
				// ReSharper restore PossibleNullReferenceException
				return View(prj.SchemaDefinition);
			}
			catch (Exception ex)
			{
				if (HandleException(ex))
					return LastError;
				throw;
			}
		}

		private static string ReadStream(Stream inputStream)
		{
			var sr = new StreamReader(inputStream);
			return sr.ReadToEnd();
		}

		private static IDataSourceService GetDataSourceService()
		{
			var binding = new BasicHttpBinding();
			var address = new EndpointAddress(
											"http://localhost:8732/Design_Time_Addresses/Dqaqs/DataSourceService/");
			var fact = new ChannelFactory<IDataSourceService>(binding, address);
			var ch = fact.CreateChannel();
			return ch;
		}
	}
}
